package com.gugee.ins.data.task.mark.service;

import com.gugee.ins.common.dal.service.brand.InsBrandDao;
import com.gugee.ins.common.dal.service.mark.InsMarkBrandDayDao;
import com.gugee.ins.common.dal.service.statistics.InsStBrandDao;
import com.gugee.ins.common.dto.InsBrandDto;
import com.gugee.ins.common.dto.RankTaskParam;
import com.gugee.ins.common.model.es.brand.InsBrandEsMapping;
import com.xiguaji.boot.toolkit.DateTimeUtils;
import com.xiguaji.boot.toolkit.elasticsearch.RestClientHelper;
import com.xxl.job.core.log.XxlJobLogger;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.TimeZone;

/**
 * ins 品牌日打点
 * @author huangxin
 */
@Component
@Slf4j
public class InsBrandMarkSvc extends AbstractMarkRankProducerHandler {
    /**
     *
     */
    private static final String DATE_FORMATTER = "yyyyMMdd";

    /**
     *
     */
    @Autowired
    public InsBrandDao insBrandDao;

    /**
     *
     */
    @Autowired
    public InsStBrandDao insStBrandDao;

    /**
     *
     */
    @Autowired
    InsMarkBrandDayDao insMarkBrandDayDao;

    /**
     * 执行
     */
    @Override
    public void handleRank(RankTaskParam taskParam) {
        long maxId;
        int startId = 1;
        int endId = taskConfig.getInsBloggerMarkDayPageSize() > 0 ? taskConfig.getInsBloggerMarkDayPageSize() : 1000;
        if(taskParam.getId() != null && taskParam.getId() > 0){
            startId = taskParam.getId();
            endId = taskParam.getId();
            maxId = taskParam.getId() + 1L;
        } else {
            maxId = objectTotals();
        }

        long dateCode = 0;
        if(!StringUtils.isEmpty(taskParam.getDateCode())){
            dateCode = getDateTime(taskParam.getDateCode());
        }

        // 循环爬取的id打点
        while(endId < maxId || startId == 1){
            try{
                List<InsBrandDto> markInfo = insBrandDao.findInsBrandDtoByPages(startId,endId);
                if(markInfo != null && !markInfo.isEmpty()){
                    for(InsBrandDto insBrandDto : markInfo) {
                        if(StringUtils.isEmpty(insBrandDto.getCategoryName())){
                            insBrandDto.setCategoryName("");
                        }
                        mark(insBrandDto,taskParam.getTypeCode());
                        markDay(insBrandDto,taskParam.getTypeCode(),dateCode);
                        markWeek(insBrandDto,taskParam.getTypeCode(),dateCode);
                        markMonth(insBrandDto,taskParam.getTypeCode(),dateCode);
                    }
                    toEs(markInfo);
                }
            }catch (Exception e){
                log.info("ins 品牌打点失败 id, msg :{}", e.getMessage());
                XxlJobLogger.log("ins 品牌打点失败 id, msg :{}", e.getMessage());
            }
            startId += taskConfig.getInsBloggerMarkDayPageSize();
            endId += taskConfig.getInsBloggerMarkDayPageSize();
        }
    }

    /**
     * 同步到ES
     * @param markInfo
     */
    private void toEs(List<InsBrandDto> markInfo){
        List<InsBrandEsMapping> insBrandEsMappings = new ArrayList<>(markInfo.size());
        markInfo.forEach( m-> insBrandEsMappings.add(insStBrandDao.findEsMappingByBid(m.getId())));
        if(!insBrandEsMappings.isEmpty()){
            RestClientHelper.upsert(taskConfig.getInsBrandIndex(),insBrandEsMappings);
        }
    }

    /**
     * 获取最大的id
     * @return
     */
    public long objectTotals() {
        return insBrandDao.getMaxId();
    }

    /**
     * 近30天打点
     * @param insBrandDto
     * @param typeCode
     */
    public void mark(InsBrandDto insBrandDto,int typeCode){
        if(typeCode == 0 || typeCode == 1){
            try{
                // 统计表里查看是否存在不存在则先插入一条记录
                boolean isExist = insStBrandDao.findExist(insBrandDto.getId());
                if(!isExist){
                    insStBrandDao.insertEmptyData(insBrandDto.getId());
                }
                long limitTimeEnd = System.currentTimeMillis() / 1000;
                long limitTimeStart = limitTimeEnd - 3600 * 24 * 30;
                insStBrandDao.updateBrandSt(insBrandDto.getId(),limitTimeStart,limitTimeEnd);
            }catch (Exception e){
                log.error("ins 品牌近30天统计打点失败 id:{}, msg :{}",insBrandDto.getId(), e.getMessage());
            }
        }
    }

    /**
     * 日打点
     * @param insBrandDto
     * @param typeCode
     */
    public void markDay(InsBrandDto insBrandDto,int typeCode,long dateCode){
        if(typeCode == 0 || typeCode == 2){
            try{
                Calendar calendar = Calendar.getInstance();
                // 设置时间
                if(dateCode > 0){
                    calendar.setTimeInMillis(dateCode);
                }
                calendar.setTimeZone(TimeZone.getTimeZone("UTC"));
                calendar.set(Calendar.HOUR_OF_DAY,0);
                calendar.set(Calendar.MINUTE,0);
                calendar.set(Calendar.SECOND,0);
                long limitTimeEnd = calendar.getTimeInMillis() / 1000;
                long limitTimeStart = limitTimeEnd - 24 * 3600;

                int markDay = Integer.parseInt(DateTimeUtils.formatSecond(limitTimeStart,DATE_FORMATTER,"UTC"));
                insMarkBrandDayDao.insertMark(insBrandDto.getId(),insBrandDto.getCategoryName(),limitTimeStart,limitTimeEnd - 1,markDay,1);
            }catch (Exception e){
                log.error("ins 品牌近日统计打点失败 id:{}, msg :{}",insBrandDto.getId(), e.getMessage());
            }
        }
    }

    /**
     * 周打点
     * @param insBrandDto
     * @param typeCode
     */
    public void markWeek(InsBrandDto insBrandDto,int typeCode,long dateCode){
        Calendar calendar = Calendar.getInstance();
        // 设置时间
        if(dateCode > 0){
            calendar.setTimeInMillis(dateCode);
        }
        if(typeCode == 3 || (typeCode == 0 && isMonday(calendar))){
            try{
                calendar.setTimeZone(TimeZone.getTimeZone("UTC"));
                calendar.set(Calendar.HOUR_OF_DAY,0);
                calendar.set(Calendar.MINUTE,0);
                calendar.set(Calendar.SECOND,0);
                calendar.set(Calendar.DAY_OF_WEEK, calendar.getActualMinimum(Calendar.DAY_OF_WEEK));
                long limitTimeEnd = calendar.getTimeInMillis() / 1000 + 24 * 3600 - 1;
                long limitTimeStart = limitTimeEnd - 7 * 24 * 3600 + 1;

                int markDay = Integer.parseInt(DateTimeUtils.formatSecond(limitTimeEnd,DATE_FORMATTER,"UTC"));
                insMarkBrandDayDao.insertMark(insBrandDto.getId(),insBrandDto.getCategoryName(),limitTimeStart,limitTimeEnd,markDay,2);
            }catch (Exception e){
                log.error("ins 品牌近周统计打点失败 id:{}, msg :{}",insBrandDto.getId(), e.getMessage());
            }
        }
    }

    /**
     * 月打点
     * @param insBrandDto
     * @param typeCode
     */
    public void markMonth(InsBrandDto insBrandDto,int typeCode,long dateCode){
        Calendar calendar = Calendar.getInstance();
        // 设置时间
        if(dateCode > 0){
            calendar.setTimeInMillis(dateCode);
        }
        if(typeCode == 4 || (typeCode == 0 && isFirstDayOfMonth(calendar))){
            try{
                calendar.setTimeZone(TimeZone.getTimeZone("UTC"));
                calendar.set(Calendar.HOUR_OF_DAY,0);
                calendar.set(Calendar.MINUTE,0);
                calendar.set(Calendar.SECOND,0);
                calendar.set(Calendar.DAY_OF_MONTH, 1);
                calendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH) - 1);
                long limitTimeStart = calendar.getTimeInMillis() / 1000;
                calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
                long limitTimeEnd = calendar.getTimeInMillis() / 1000 + 24 * 3600 - 1;

                int markDay = Integer.parseInt(DateTimeUtils.formatSecond(limitTimeEnd,DATE_FORMATTER,"UTC"));
                insMarkBrandDayDao.insertMark(insBrandDto.getId(),insBrandDto.getCategoryName(),limitTimeStart,limitTimeEnd,markDay,3);
            }catch (Exception e){
                log.error("ins 品牌近月统计打点失败 id:{}, msg :{}",insBrandDto.getId(), e.getMessage());
            }
        }
    }


}
